import axios, { type AxiosRequestConfig, type AxiosError, type AxiosResponse } from "axios";

import { t } from "@/locales/i18n";
import userStore from "@/store/userStore";

import { toast } from "sonner";
import type { Result } from "#/api";
import { ResultEnum } from "#/enum";

// 创建 axios 实例
const axiosInstance = axios.create({
	baseURL: import.meta.env.VITE_APP_BASE_API,
	timeout: 50000,
	headers: { "Content-Type": "application/json;charset=utf-8" },
});

// 请求拦截
axiosInstance.interceptors.request.use(
	(config) => {
		const { tokenName, tokenValue } = userStore.getState().userToken;
		if (tokenName && tokenValue) {
			config.headers[tokenName] = tokenValue;
		}

		// 如果是FormData，删除Content-Type，让浏览器自动设置
		if (config.data instanceof FormData) {
			// 使用Axios的正确API处理headers
			if (config.headers) {
				config.headers["Content-Type"] = undefined;
			}
		}

		// 如果是文件下载请求，设置responseType为blob
		if (config.url?.includes("/download") || config.url?.includes("/export")) {
			config.responseType = "blob";
		}

		return config;
	},
	(error) => {
		// 请求错误时做些什么
		return Promise.reject(error);
	},
);

// 响应拦截
axiosInstance.interceptors.response.use(
	(res: AxiosResponse<Result>) => {
		// 处理文件下载的情况
		const contentType = res.headers["content-type"];
		if (
			contentType &&
			(contentType.includes("application/octet-stream") ||
				contentType.includes("application/pdf") ||
				contentType.includes("image/") ||
				contentType.includes("video/") ||
				contentType.includes("audio/") ||
				res.config.responseType === "blob")
		) {
			// 获取文件名
			const contentDisposition = res.headers["content-disposition"];
			let filename = "download";
			if (contentDisposition) {
				// 处理不同浏览器的文件名编码
				const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
				const matches = filenameRegex.exec(contentDisposition);
				if (matches?.[1]) {
					filename = matches[1].replace(/['"]/g, "");
					// 处理URL编码的文件名
					try {
						filename = decodeURIComponent(filename);
					} catch (e) {
						// 如果解码失败，尝试其他编码方式
						filename = filename.replace(/[^\x20-\x7E]/g, "");
					}
				}
			}

			// 直接使用响应数据创建Blob
			const blob = new Blob([res.data as unknown as BlobPart], { type: contentType });
			const url = window.URL.createObjectURL(blob);

			// 使用更兼容的下载方式
			const nav = window.navigator as any;
			if (nav.msSaveOrOpenBlob) {
				// IE10+
				nav.msSaveOrOpenBlob(blob, filename);
			} else {
				// 其他现代浏览器
				const link = document.createElement("a");
				link.style.display = "none";
				link.href = url;
				link.setAttribute("download", filename);

				// 添加到文档中并触发点击
				document.body.appendChild(link);
				link.click();

				// 清理
				setTimeout(() => {
					document.body.removeChild(link);
					window.URL.revokeObjectURL(url);
				}, 100);
			}

			return blob;
		}

		if (!res.data) throw new Error(t("sys.api.apiRequestFailed"));

		let responseData = res.data;
		if (typeof res.data === "string") {
			try {
				responseData = JSON.parse(res.data);
			} catch (e) {
				console.error("响应数据不是合法 JSON 字符串", res.data);
			}
		}
		const { code, data, message } = responseData;
		// 业务请求成功
		const hasSuccess = Reflect.has(responseData, "code") && code === ResultEnum.SUCCESS;
		if (hasSuccess) {
			return data;
		}

		// 业务请求错误
		throw new Error(message || t("sys.api.apiRequestFailed"));
	},
	(error: AxiosError<Result>) => {
		const { response, message } = error || {};

		const errMsg = response?.data?.message || message || t("sys.api.errorMessage");
		toast.error(errMsg, {
			position: "top-center",
		});

		const status = response?.status;
		// 错误处理：500 错误弹出提示
		if (status === 500) {
			toast.error(t("sys.api.errorMessage"), { position: "top-center" });
		} else if (status === 401) {
			userStore.getState().actions.clearUserInfoAndToken();
		} else {
			// 其他错误统一提示
			toast.error(errMsg, { position: "top-center" });
		}
		return Promise.reject(error);
	},
);

class APIClient {
	get<T = any>(config: AxiosRequestConfig): Promise<T> {
		return this.request({ ...config, method: "GET" });
	}

	post<T = any>(config: AxiosRequestConfig): Promise<T> {
		return this.request({ ...config, method: "POST" });
	}

	put<T = any>(config: AxiosRequestConfig): Promise<T> {
		return this.request({ ...config, method: "PUT" });
	}

	delete<T = any>(config: AxiosRequestConfig): Promise<T> {
		return this.request({ ...config, method: "DELETE" });
	}

	request<T = any>(config: AxiosRequestConfig): Promise<T> {
		return new Promise((resolve, reject) => {
			axiosInstance
				.request<any, AxiosResponse<Result>>(config)
				.then((res: AxiosResponse<Result>) => {
					resolve(res as unknown as Promise<T>);
				})
				.catch((e: Error | AxiosError) => {
					reject(e);
				});
		});
	}
}
export default new APIClient();
